/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.service.impl;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.bo.GoodsBO;
import com.xy.biz.base.domain.bo.GoodsBatchBO;
import com.xy.biz.base.domain.enums.GoodsBatchStatusEnum;
import com.xy.biz.base.domain.enums.QualityGuaranteePeriodUnitEnum;
import com.xy.biz.base.domain.query.GoodsBatchQuery;
import com.xy.biz.base.manager.GoodsBatchManager;
import com.xy.biz.base.manager.GoodsManager;
import com.xy.biz.base.service.GoodsBatchService;
import com.xy.lang.domain.Result;
import com.xy.lang.util.EnumUtils;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zgy
 * @date 2021-9-22
 */
@Service
public class GoodsBatchServiceImpl implements GoodsBatchService {

    @Autowired
    private GoodsBatchManager goodsBatchManager;
    @Autowired
    private GoodsManager goodsManager;
    @Autowired
    private DictClient dictClient;

    @Override
    public Result<?> saveGoodsBatch(GoodsBatchBO goodsBatch) {
        return saveAllGoodsBatch(Arrays.asList(goodsBatch));
    }

    @Override
    public Result<?> saveAllGoodsBatch(Collection<GoodsBatchBO> collection) {
        Set<Long> goodsIdSet = new HashSet<>();
        for(GoodsBatchBO goodsBatch : collection) {
            if(Objects.isNull(goodsBatch.getProductionDate())) {
                LocalDate localDate = goodsBatch.fromBatchCode();
                if(localDate == null) {
                    return Result.ofBadRequest("即没有设置生产日期，也无法从批号【" + goodsBatch.getGoodsBatchCode() + "】导出生产日期来");
                }
                goodsBatch.setProductionDate(localDate);
            }
            goodsIdSet.add(goodsBatch.getGoodsId());
        }
        List<GoodsBO> goodsList = goodsManager.listGoodsById(goodsIdSet);
        if(!Objects.equals(goodsList.size(), goodsIdSet.size())) {
            return Result.ofBadRequest("不存在的货品：" + goodsIdSet.removeAll(
                    goodsList.stream().map(GoodsBO::getGoodsId).collect(Collectors.toSet())));
        }
        SaveGoodsBatchContext saveGoodsBatchContext = new SaveGoodsBatchContext();
        Map<Long, GoodsBO> goodsMap = goodsList.stream().collect(Collectors.toMap(GoodsBO::getGoodsId, e -> e));
        LocalDateTime now = LocalDateTime.now();
        for(GoodsBatchBO goodsBatch : collection) {
            GoodsBO goods = goodsMap.get(goodsBatch.getGoodsId());
            goodsBatch.setGoodsCode(goods.getGoodsCode());
            goodsBatch.setGoodsFullCode(goods.getGoodsFullCode());
            goodsBatch.setGoodsAbbr(goods.getGoodsAbbr());
            if(Objects.isNull(goodsBatch.getExpirationDate())) {
                goodsBatch.computeExpirationDate(goods.getQualityGuaranteePeriod(),
                        EnumUtils.getEnum(QualityGuaranteePeriodUnitEnum.values(), goods.getQualityGuaranteePeriodUnit()));
            }
            if(Objects.isNull(goodsBatch.getRiskDate())) {
                goodsBatch.computeRiskDate(saveGoodsBatchContext.getDefaultRiskFactor(),
                        saveGoodsBatchContext.getDefaultFactorPeriodUnit());
            }
            if(Objects.isNull(goodsBatch.getFreezeDate())) {
                goodsBatch.computeFreezeDate(saveGoodsBatchContext.getDefaultFreezeFactor(),
                        saveGoodsBatchContext.getDefaultFactorPeriodUnit());
            }

            goodsBatch.setGoodsOwnerId(0L);
            goodsBatch.setStatus(GoodsBatchStatusEnum.ORDINARY.getCode());
            goodsBatch.setTenantId(UserContextHolder.getTenantId());
            goodsBatch.setCreateUserId(UserContextHolder.getUserId());
            goodsBatch.setCreateUserName(UserContextHolder.getUserName());
            goodsBatch.setCreateTime(now);
            goodsBatch.setUpdateUserId(UserContextHolder.getUserId());
            goodsBatch.setUpdateUserName(UserContextHolder.getUserName());
            goodsBatch.setUpdateTime(now);
        }
        int affectedRows = goodsBatchManager.saveAllGoodsBatch(collection);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    class SaveGoodsBatchContext {
        private Map<String, String> goodsQualitySetting;
        private Integer defaultRiskFactor;
        private Integer defaultFreezeFactor;

        public SaveGoodsBatchContext() {
            goodsQualitySetting = dictClient.mapDict("goods_quality_setting");
        }

        public Integer getDefaultRiskFactor() {
            if(defaultRiskFactor == null) {
                try {
                    defaultRiskFactor = Integer.parseInt(goodsQualitySetting.get("defaultRiskFactor"));
                } catch (NumberFormatException e) {
                    defaultRiskFactor = 6;
                }
            }

            return defaultRiskFactor;
        }

        public Integer getDefaultFreezeFactor() {
            if(defaultFreezeFactor == null) {
                try {
                    defaultFreezeFactor = Integer.parseInt(goodsQualitySetting.get("defaultFreezeFactor"));
                } catch (NumberFormatException e) {
                    defaultFreezeFactor = 1;
                }
            }

            return defaultFreezeFactor;
        }

        public QualityGuaranteePeriodUnitEnum getDefaultFactorPeriodUnit() {
            return QualityGuaranteePeriodUnitEnum.MONTH;
        }
    }

    @Override
    public Result<?> updateGoodsBatch(GoodsBatchBO goodsBatchBO) {
        int affectedRows = goodsBatchManager.updateGoodsBatch(goodsBatchBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteGoodsBatch(Long goodsBatchId) {
        int affectedRows = goodsBatchManager.deleteGoodsBatch(goodsBatchId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public GoodsBatchBO getGoodsBatch(Long goodsBatchId) {
        return goodsBatchManager.getGoodsBatch(goodsBatchId);
    }

    @Override
    public List<GoodsBatchBO> listGoodsBatchById(Collection<Long> collection) {
        return goodsBatchManager.listGoodsBatchById(collection);
    }

    @Override
    public List<GoodsBatchBO> listGoodsBatchByGoodsId(Collection<Long> collection) {
        GoodsBatchQuery query = GoodsBatchQuery.builder()
                .goodsIdSet(collection.stream().collect(Collectors.toSet()))
                .status(GoodsBatchStatusEnum.ORDINARY.getCode())
                .tenantId(UserContextHolder.getTenantId())
                .build();
        return goodsBatchManager.listGoodsBatchByGoods(query);
    }

    @Override
    public List<GoodsBatchBO> listGoodsBatchByGoodsCode(Collection<String> collection) {
        GoodsBatchQuery query = GoodsBatchQuery.builder()
                .goodsCodeSet(collection.stream().collect(Collectors.toSet()))
                .status(GoodsBatchStatusEnum.ORDINARY.getCode())
                .tenantId(UserContextHolder.getTenantId())
                .build();
        return goodsBatchManager.listGoodsBatchByGoods(query);
    }

    @Override
    public List<GoodsBatchBO> listGoodsBatchByGoodsAndBatch(Collection<GoodsBatchQuery> queryCollection) {
        queryCollection.forEach(e -> {
            e.setTenantId(UserContextHolder.getTenantId());
        });
        return goodsBatchManager.listGoodsBatchByGoodsAndBatch(queryCollection);
    }

    @Override
    public List<GoodsBatchBO> listGoodsBatch(GoodsBatchQuery query) {
        return goodsBatchManager.listGoodsBatch(query);
    }

    @Override
    public int countGoodsBatch(GoodsBatchQuery query) {
        return goodsBatchManager.countGoodsBatch(query);
    }

}
